package com.jzo2o.customer.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jzo2o.api.customer.dto.response.AddressBookResDTO;
import com.jzo2o.api.publics.MapApi;
import com.jzo2o.api.publics.dto.response.LocationResDTO;
import com.jzo2o.common.expcetions.ForbiddenOperationException;
import com.jzo2o.common.model.CurrentUserInfo;
import com.jzo2o.common.model.PageResult;
import com.jzo2o.common.utils.BeanUtils;
import com.jzo2o.common.utils.CollUtils;
import com.jzo2o.common.utils.NumberUtils;
import com.jzo2o.common.utils.StringUtils;
import com.jzo2o.customer.mapper.AddressBookMapper;
import com.jzo2o.customer.model.domain.AddressBook;
import com.jzo2o.customer.model.dto.request.AddressBookPageQueryReqDTO;
import com.jzo2o.customer.model.dto.request.AddressBookUpsertReqDTO;
import com.jzo2o.customer.service.IAddressBookService;
import com.jzo2o.mvc.utils.UserContext;
import com.jzo2o.mysql.utils.PageHelperUtils;
import com.jzo2o.mysql.utils.PageUtils;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 地址薄 服务实现类
 * </p>
 *
 * @author itcast
 * @since 2023-07-06
 */
@Service
public class AddressBookServiceImpl extends ServiceImpl<AddressBookMapper, AddressBook> implements IAddressBookService {

    @Autowired
    private MapApi mapApi;

    @Override
    public List<AddressBookResDTO> getByUserIdAndCity(Long userId, String city) {

        List<AddressBook> addressBooks = lambdaQuery()
                .eq(AddressBook::getUserId, userId)
                .eq(AddressBook::getCity, city)
                .list();
        if(CollUtils.isEmpty(addressBooks)) {
            return new ArrayList<>();
        }
        return BeanUtils.copyToList(addressBooks, AddressBookResDTO.class);
    }

    /**
     * 获取默认地址
     *
     * @return
     */
    @Override
    public AddressBookResDTO getDefaultAddress() {
        //第一步获取用户ID，然后才能查询默认地址
        Long userId = UserContext.currentUserId();

        AddressBook addressBook = this.getOne(new LambdaQueryWrapper<AddressBook>()
                .eq(AddressBook::getUserId, userId)
                .eq(AddressBook::getIsDefault, 1)
                .eq(AddressBook::getIsDeleted, 0));
        if(ObjectUtil.isEmpty(addressBook)) {
            return null;
        }
        return BeanUtils.copyProperties(addressBook, AddressBookResDTO.class);
    }

    /**
     * 新增地址簿
     *
     * @param reqDTO
     */
    @Override
    public void insertAddressBook(AddressBookUpsertReqDTO reqDTO) {
        if(ObjectUtil.isEmpty(reqDTO.getLocation())) {
            //这里是经纬度为空，我们需要根据写的地址信息进行获取经纬度
            LocationResDTO locationByAddress = mapApi.getLocationByAddress(reqDTO.getAddress());
            reqDTO.setLocation(locationByAddress.getLocation());
        }
        Long userId = UserContext.currentUserId();

        AddressBook addressBook = BeanUtil.copyProperties(reqDTO, AddressBook.class);
        addressBook.setUserId(userId);
        addressBook.setLon(Double.valueOf(reqDTO.getLocation().split(",")[0]));
        addressBook.setLat(Double.valueOf(reqDTO.getLocation().split(",")[1]));

        //如果当前加的是默认地址的话，我需要把其他的默认地址干掉！
        if (reqDTO.getIsDefault() == 1) {
            List<AddressBook> addressBooks = baseMapper.selectList(new LambdaQueryWrapper<AddressBook>()
                    .eq(AddressBook::getUserId, addressBook.getUserId())
                    .eq(AddressBook::getIsDefault, 1)
                    .eq(AddressBook::getIsDeleted, 0));
            if(!CollectionUtil.isEmpty(addressBooks)) {
                addressBooks.forEach(address -> {
                    this.update(new LambdaUpdateWrapper<AddressBook>()
                            .eq(AddressBook::getId, address.getId())
                            .set(AddressBook::getIsDefault, 0));
                });
            }
        }
        this.save(addressBook);
    }

    /**
     * 地址簿列表
     *
     * @param reqDto
     * @return
     */
    @Override
    public PageResult<AddressBookResDTO> findByPage(AddressBookPageQueryReqDTO reqDto) {
        List<AddressBook> addressBooks = baseMapper.selectList(new LambdaQueryWrapper<AddressBook>()
                .eq(AddressBook::getIsDeleted, 0)
                .eq(AddressBook::getUserId, UserContext.currentUserId()));
        return PageHelperUtils.selectPage(reqDto, ()-> BeanUtil.copyToList(addressBooks, AddressBookResDTO.class));
    }

    /**
     * 根据ID地址簿查询详细信息
     *
     * @param id
     * @return
     */
    @Override
    public AddressBookResDTO getAddressById(Long id) {

        return BeanUtil.copyProperties(baseMapper.selectById(id), AddressBookResDTO.class);
    }

    /**
     * 根据ID更新地址簿信息
     *
     * @param reqDTO
     */
    @Override
    public void updateAddressById(AddressBookUpsertReqDTO reqDTO, Long id) {
        if(ObjectUtil.isEmpty(reqDTO.getLocation())) {
            //这里是经纬度为空，我们需要根据写的地址信息进行获取经纬度
            LocationResDTO locationByAddress = mapApi.getLocationByAddress(reqDTO.getAddress());
            reqDTO.setLocation(locationByAddress.getLocation());
        }
        Long userId = UserContext.currentUserId();

        AddressBook addressBook = BeanUtil.copyProperties(reqDTO, AddressBook.class);
        addressBook.setUserId(userId);
        addressBook.setLon(Double.valueOf(reqDTO.getLocation().split(",")[0]));
        addressBook.setLat(Double.valueOf(reqDTO.getLocation().split(",")[1]));

        //如果当前加的是默认地址的话，我需要把其他的默认地址干掉！
        if (reqDTO.getIsDefault() == 1) {
            List<AddressBook> addressBooks = baseMapper.selectList(new LambdaQueryWrapper<AddressBook>()
                    .eq(AddressBook::getUserId, addressBook.getUserId())
                    .eq(AddressBook::getIsDefault, 1)
                    .eq(AddressBook::getIsDeleted, 0));
            if(!CollectionUtil.isEmpty(addressBooks)) {
                addressBooks.forEach(address -> {
                    this.update(new LambdaUpdateWrapper<AddressBook>()
                            .eq(AddressBook::getId, address.getId())
                            .set(AddressBook::getIsDefault, 0));
                });
            }
        }
        addressBook.setId(id);
        this.updateById(addressBook);
    }

    /**
     * 批量删除或者是单独删除地址簿
     *
     * @param ids
     */
    @Override
    public void deleteAddressByIds(List<Long> ids) {
        ids.forEach(id->{
            this.update(new LambdaUpdateWrapper<AddressBook>()
                    .eq(AddressBook::getId, id)
                    .set(AddressBook::getIsDeleted, 1));
        });
    }

    /**
     * 改变默认状态
     *
     * @param flag
     * @param id
     */
    @Override
    public void updateAddressDefault(Integer flag, Long id) {
        AddressBook addressBook = this.getById(id);
        //如果当前加的是默认地址的话，我需要把其他的默认地址干掉！
        if (flag == 1) {
            List<AddressBook> addressBooks = baseMapper.selectList(new LambdaQueryWrapper<AddressBook>()
                    .eq(AddressBook::getUserId, addressBook.getUserId())
                    .eq(AddressBook::getIsDefault, 1)
                    .eq(AddressBook::getIsDeleted, 0));
            if (!CollectionUtil.isEmpty(addressBooks)) {
                addressBooks.forEach(address -> {
                    this.update(new LambdaUpdateWrapper<AddressBook>()
                            .eq(AddressBook::getId, address.getId())
                            .set(AddressBook::getIsDefault, 0));
                });
            }
            this.update(new LambdaUpdateWrapper<AddressBook>()
                    .eq(AddressBook::getId, id)
                    .set(AddressBook::getIsDefault, 1));
        } else {
            this.update(new LambdaUpdateWrapper<AddressBook>()
                    .eq(AddressBook::getId, id)
                    .set(AddressBook::getIsDefault, 0));
        }
    }
}












